package main.leetcode.clockin.March;

/**
 * 169.多数元素
 *
 * <p>给定一个大小为 n 的数组，找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
 *
 * <p>你可以假设数组是非空的，并且给定的数组总是存在多数元素。
 *
 * <p>示例 1: 输入: [3,2,3] 输出: 3
 *
 * <p>示例 2: 输入: [2,2,1,1,1,2,2] 输出: 2
 *
 * <p>来源：力扣（LeetCode） 链接：https://leetcode-cn.com/problems/majority-element
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class day13 {
    public static void main(String[] args) {
        System.out.println(new day13().majorityElement(new int[] {3, 2, 3}));
    }

    // Boyer-Moore 投票算法
    public int majorityElement1(int[] nums) {
        int count = 0;
        int candidate = nums[0];
        for (int val : nums) {
            if (count == 0) candidate = val;
            if (val == candidate) count++;
            else count--;
        }
        return candidate;
    }

    // 分治
    public int majorityElement(int[] nums) {
        return majorityElement(nums, 0, nums.length - 1);
    }

    private int majorityElement(int[] nums, int l, int r) {
        if (l >= r) return nums[l];
        int m = l + (r - l) / 2;
        int left = majorityElement(nums, l, m); // 找左部的众数
        int right = majorityElement(nums, m + 1, r); // 找右部的众数
        if (left == right) return left; // 相等则就是他

        // 不相等则进行计数对比，看谁出现次数多
        int countLeft = countInRange(nums, left, l, r);
        int countRight = countInRange(nums, right, l, r);

        return countLeft > countRight ? left : right;
    }

    private int countInRange(int[] nums, int val, int l, int r) {
        int count = 0;
        for (int i = l; i <= r; i++) if (nums[i] == val) count++;
        return count;
    }
}
